package org.runecore.rs2.plugin;

import java.io.File;
import java.io.FileInputStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;

import org.runecore.Launch;
import org.runecore.rs2.net.codec.AbstractGameRevision;
import org.runecore.rs2.plugin.info.PluginInformation;

/**
 * RuneCore Aug 25, 2011
 * @author Harry Andreas<Harry@RuneCore.org>
 */

public class PluginFactory {

	/**
	 * An <code>LinkedList</code> containing registered plugins
	 */
	private LinkedList<Plugin> registeredPlugins = new LinkedList<Plugin>();

	/**
	 * Constructor
	 */
	public PluginFactory() {
		try {
			readPlugins();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * Reads <code>Plugin</code> property files and loads
	 * @throws Exception
	 */
	public void readPlugins() throws Exception {
		List<PluginInformation> list = new ArrayList<PluginInformation>();
		File[] plugins = new File("./data/env/plugin/props/").listFiles();
		Properties props = new Properties();
		for (File f : plugins) {
			props.load(new FileInputStream(f));
			PluginInformation info = new PluginInformation();
			info.author = props.getProperty("plugin-author");
			info.pluginName = props.getProperty("plugin-name");
			info.pluginClass = props.getProperty("plugin-class");
			info.version = Double.parseDouble(props.getProperty("plugin-version"));
			info.jarFile = Launch.getEnv().getFS().getFileByName(props.getProperty("plugin-file"));
			String nonPlugin = props.getProperty("non");
			if(nonPlugin != null) {
				this.loadNonPlugin(info);
				continue;
			}
			list.add(info);
			props.clear();
		}
		createPlugins(list);
	}

	/**
	 * Creates the list of the <code>Plugin</code>'s
	 * @param list
	 * @throws Exception
	 */
	public void createPlugins(List<PluginInformation> list) throws Exception {
		for (PluginInformation info : list) {
			Plugin plug = loadPlugin(info);
			if (plug != null) {
				registeredPlugins.add(plug);
				if (plug instanceof AbstractGameRevision) {
					Launch.getEnv().getLoadedRevisions().add((AbstractGameRevision) plug);
				}
			}
		}
	}

	/**
	 * Loads a <code>Plugin</code> from file
	 * @param info
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("rawtypes")
	public Plugin loadPlugin(PluginInformation info) throws Exception {
		File f = info.jarFile;
		URL jarfile = new URL("jar", "","file:" + f.getCanonicalPath()+"!/");
		URL[] urls = new URL[] { jarfile };
		ClassLoader cl = new URLClassLoader(urls);
		Class plugin = cl.loadClass(info.pluginClass);
		return (Plugin) plugin.newInstance();
	}
	
	/**
	 * Loads a <code>Plugin</code> from file
	 * @param info
	 * @return
	 * @throws Exception
	 */
	public void loadNonPlugin(PluginInformation info) throws Exception {
		File f = info.jarFile;
		URL jarfile = new URL("jar", "","file:" + f.getCanonicalPath()+"!/");
		URL[] urls = new URL[] { jarfile };
		ClassLoader cl = new URLClassLoader(urls);
		cl.loadClass(info.pluginClass);
	}

	
}